/*************************************************************
 * File: OperationAuthorityInterceptor.java
 * Author: Huang Shaobin
 * Email: Shaobin.Software@gmail.com Shaobin_Software@163.com 
 * Date: Jan 31, 2013 3:24:27 AM
 * Description: 
 * Copyright (c) 2012
 ************************************************************/
package snow.core.security;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.util.Assert;

import snow.core.context.AccessContext;

/**
 * 操作权限拦截器
 */
public class OperationAuthorityInterceptor implements MethodInterceptor, InitializingBean {

	private final Log log = LogFactory.getLog(getClass());

	private Map<String, String> errorMsg;
	private MessageSource messageSource;
	private SecurityService securityService;

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(messageSource, "The property[messageSource] must not be null!");
		Assert.notNull(securityService, "The property[securityService] must not be null!");
		if (MapUtils.isEmpty(errorMsg)) {
			errorMsg = new HashMap<String, String>(2);
			errorMsg.put("code", "200100");
			errorMsg.put("message", "failure.user.unauthorized");
		}
		errorMsg = Collections.unmodifiableMap(errorMsg);
	}

	public Map<String, String> getErrorMsg() {
		return this.errorMsg;
	}

	public SecurityService getSecurityService() {
		return securityService;
	}

	/**
	 * @param invocation
	 * @return
	 * @throws Throwable
	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		log.debug("开始执行权限校验……");
		final Object target = invocation.getThis(); // 目标对象
		final Method method = invocation.getMethod(); // 目标方法
		final String resourceUri = SecurityHelper.getResourceUriFrom(target, method); // 获取资源信息
		if (log.isDebugEnabled()) { // 增加此判断是为了在运行时减少没必要的字符串生成
			log.debug("当前调用资源信息为：[" + resourceUri + "]");
		}
		final int operation = SecurityHelper.getOperationFrom(method); // 获取操作权限值
		if (log.isDebugEnabled()) {
			log.debug("当前操作资源的权限值为：[" + operation + "]");
		}
		try {
			if (!securityService.canAccessResource(resourceUri, operation)) {
				Map<String, String> errorMsg = new HashMap<String, String>(this.errorMsg);
				String message = errorMsg.get("message");
				if (StringUtils.isNotBlank(message)) {
					AccessContext context = AccessContext.get();
					Object locales = context.get("request_locales");
					if (locales instanceof List) {
						List<?> list = (List<?>) locales;
						Object item = CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
						Locale locale = item instanceof Locale ? (Locale) item : Locale.getDefault();
						message = messageSource.getMessage(message, ArrayUtils.EMPTY_OBJECT_ARRAY, locale);
						errorMsg.put("message", message);
					}
				}
				return errorMsg;
			}
			return invocation.proceed(); // 继续执行
		} finally {

		}
	}

	public void setErrorMsg(Map<String, String> errorMsg) {
		this.errorMsg = errorMsg;
	}

	public void setSecurityService(SecurityService securityService) {
		this.securityService = securityService;
	}

	public MessageSource getMessageSource() {
		return this.messageSource;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

}
